package com.hyt.it.ogt.ks.controller;


import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hyt.common.apiInfor.ApiResponse;
import com.hyt.common.apiInfor.DataType;
import com.hyt.common.apiInfor.ParamType;
import com.hyt.it.ogt.ks.base.BaseController;
import com.hyt.it.ogt.ks.config.KsBizRunTimeException;
import com.hyt.it.ogt.ks.enums.BizStatusCode;
import com.hyt.it.ogt.ks.exception.KsException;
import com.hyt.it.ogt.ks.feign.KwClient;
import com.hyt.it.ogt.ks.feign.model.param.FaceAuthFailParam;
import com.hyt.it.ogt.ks.feign.model.vo.FaceAuthFailVO;
import com.hyt.it.ogt.ks.model.entity.CandidateProcess;
import com.hyt.it.ogt.ks.model.vo.CandidateStatusVO;
import com.hyt.it.ogt.ks.model.vo.OverScreenLogVO;
import com.hyt.it.ogt.ks.model.vo.RedoExamReqVO;
import com.hyt.it.ogt.ks.service.ICandidateLogService;
import com.hyt.it.ogt.ks.service.ICandidatePassService;
import com.hyt.it.ogt.ks.service.ICandidateProcessService;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;

/**
 * <p>
 * 考生考试过程表 前端控制器
 * </p>
 *
 * @author chengxh
 * @since 2020-06-17
 */
@RestController
@Api(tags = "6.考生考试过程", value = "考生考试过程")
@ApiSort(value = 6)
@RequestMapping("/ks/candidate-process")
@Slf4j
public class CandidateProcessController extends BaseController {
    @Resource
    private ICandidateLogService iCandidateLogService;
    @Resource
    private ICandidateProcessService iCandidateProcessService;
    @Resource
    private ICandidatePassService iCandidatePassService;
    @Resource
    private KwClient kwClient;

    @ApiOperation(value = "6.1 获取剩余时长", notes = "获取考生的剩余时长，状态码：20000:成功，" +
            "42060101：异常<br/>前端每隔X频率调用此接口获取考生的剩余时长(毫秒，如果值为0，则调用交卷)，同时服务端会记录考生的时长")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "examId", value = "考试项目id", dataType = DataType.STRING,
                    paramType = ParamType.QUERY, required = true),
            @ApiImplicitParam(name = "candidateId", value = "考生id", dataType = DataType.STRING,
                    paramType = ParamType.QUERY, required = true),
            @ApiImplicitParam(name = "paperSort", value = "试卷顺序号", dataType = DataType.STRING,
                    paramType = ParamType.QUERY, required = true)
    })
    @ApiOperationSort(1)
    @GetMapping("getTimeLength")
    public ApiResponse<CandidateStatusVO> getTimeLength(String examId, String candidateId, Integer paperSort){
        iCandidateLogService.printlnLog("getTimeLength接口请求参数", examId, candidateId, paperSort.toString());
        try {
            CandidateStatusVO vo = iCandidateProcessService.getTimeLength(examId, candidateId, paperSort);
            return ApiResponse.<CandidateStatusVO>builder().code(BizStatusCode.KS_SUCCESS_OK.getCode()).data(vo).build();
        } catch (Exception e) {
            log.error(StringUtils.join(BizStatusCode.GET_SURPLUS_DURATION.getCode(), ": "), e);
            return ApiResponse.<CandidateStatusVO>builder().code(BizStatusCode.GET_SURPLUS_DURATION.getCode()).build();
        }
    }
    
    @ApiOperation(value = "6.2 获取双监控登录状态", notes = "获取双监控登录状态，状态码：20000:成功，42060105：异常")
    @ApiImplicitParams({ @ApiImplicitParam(name = "candidateId", value = "考生id", dataType = DataType.STRING, paramType = ParamType.QUERY, required = true)})
    @ApiOperationSort(2)
    @GetMapping("getMobileLoginStatus")
    public ApiResponse getMobileLoginStatus(@RequestParam String examId, @RequestParam String candidateId){
        try {
        	QueryWrapper<CandidateProcess> query =  Wrappers.query();
        	query.lambda().select(CandidateProcess::getId, CandidateProcess::getMobileLoginStatus)
                    .eq(CandidateProcess::getExamId, examId)
                    .eq(CandidateProcess::getCandidateId, candidateId)
        	        .eq(CandidateProcess::getDelFlag, false);
        	CandidateProcess candidateProcess = iCandidateProcessService.getOne(query);
            return ApiResponse.builder()
                    .code(BizStatusCode.KS_SUCCESS_OK.getCode())
                    .data(candidateProcess.getMobileLoginStatus())
                    .build();
        } catch (Exception e) {
            log.error(StringUtils.join(BizStatusCode.CANDIDATE_APP_LOGIN_FAIL_CODE.getCode(), ": "), e);
            return ApiResponse.builder()
                    .code(BizStatusCode.CANDIDATE_APP_LOGIN_FAIL_CODE.getCode())
                    .build();
        }
    }

    @ApiOperation(value = "6.3 重置考试(不满意重做)", notes = "状态码：20000:成功，42060102：参数校验不通过，42060103：异常")
    @ApiOperationSort(3)
    @PutMapping("redoExam")
    public ApiResponse redoExam(@RequestBody @Valid RedoExamReqVO param, BindingResult bindingResult) {
        if(bindingResult.hasErrors()) {
            return ApiResponse.builder().code(BizStatusCode.REDO_EXAM_PARAM_ERROR.getCode()).build();
        }
        try {
            iCandidateProcessService.redoExam(param.getExamId(), param.getCandidateId());
            return ApiResponse.builder().code(BizStatusCode.KS_SUCCESS_OK.getCode()).build();
        } catch (KsBizRunTimeException e) {
            return ApiResponse.builder().code(e.getCode()).build();
        } catch (Exception e) {
            log.error("{}", e);
            return ApiResponse.builder().code(BizStatusCode.REDO_EXAM_FAIL.getCode()).build();
        }
    }

    @ApiOperation(value = "6.4 获取考生已切屏次数", notes = "状态码：20000:成功，42061401：异常", response = ApiResponse.class)
    @ApiImplicitParams({
    	@ApiImplicitParam(name = "examId", value = "考试项目id", dataType = DataType.STRING,
                paramType = ParamType.QUERY, required = true),
        @ApiImplicitParam(name = "candidateId", value = "考生id", dataType = DataType.STRING,
                paramType = ParamType.QUERY, required = true)
    	})
    @ApiOperationSort(4)
    @GetMapping("getAlreadyOverScreenCount")
    public ApiResponse getAlreadyOverScreenCount(@RequestParam String examId, @RequestParam String candidateId) {
    	try {    		
            return ApiResponse.builder()
                    .code(BizStatusCode.KS_SUCCESS_OK.getCode())
                    .data(iCandidateProcessService.getAlreadyOverScreenCount(examId, candidateId))
                    .build();
        } catch (Exception e) {
            log.error(StringUtils.join(BizStatusCode.GET_REMAIN_SCREEN_NUM_ERROR.getCode(), ": "), e);
            return ApiResponse.builder()
                    .code(BizStatusCode.GET_REMAIN_SCREEN_NUM_ERROR.getCode())
                    .build();
        }
    }

    @ApiOperation(value = "6.6 考生举手")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "examId", value = "考试项目id", dataType = DataType.STRING,
                    paramType = ParamType.QUERY, required = true),
            @ApiImplicitParam(name = "candidateId", value = "考生ID", dataType = DataType.STRING,
                    paramType = ParamType.QUERY, required = true)
    })
    @ApiOperationSort(6)
    @GetMapping("handUp")
    public ApiResponse handUp(@RequestParam String examId, @RequestParam String candidateId) {
        return kwClient.handUp(examId, candidateId);
    }

    @ApiOperation(value = "6.7 切屏记录")
    @ApiOperationSort(7)
    @PostMapping("overScreenLog")
    public ApiResponse overScreenLog(@RequestBody @Valid OverScreenLogVO overScreenLogVO, BindingResult bindingResult) {
        try {
            log.info("切屏记录：{}", JSON.toJSONString(overScreenLogVO));
            if(bindingResult.hasErrors() || overScreenLogVO == null || overScreenLogVO.getCandidateId() == null) {
                return ApiResponse.builder().code(BizStatusCode.OVER_SCREEN_PARAM_NULL.getCode()).build();
            }
            iCandidateProcessService.overScreenLog(overScreenLogVO);
        } catch (Exception e) {
            log.error("记录切屏异常：{}", e);
        }
        return ApiResponse.builder().code(BizStatusCode.KS_SUCCESS_OK.getCode()).build();
    }

    @ApiOperation(value = "6.8 获取跳过考试步骤", notes = "")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "examId", value = "考试项目id", dataType = DataType.STRING,
                    paramType = ParamType.QUERY, required = true),
            @ApiImplicitParam(name = "candidateId", value = "考生id", dataType = DataType.STRING,
                    paramType = ParamType.QUERY, required = true)
    })
    @ApiOperationSort(8)
    @GetMapping("getCandidatePassSteps")
    public ApiResponse<List<String>> getCandidatePassSteps(@RequestParam String examId, @RequestParam String candidateId){

        log.info("获取跳过考试步骤参数，examId：{}，candidateId：{} ",examId,candidateId);
        try {
            if (StringUtils.isBlank(examId) || StringUtils.isBlank(candidateId)) {
                return ApiResponse.<List<String>>builder().code(BizStatusCode.PASS_STEP_PARAM_NONE.getCode()).build();
            }

            return ApiResponse.<List<String>>builder().code(BizStatusCode.KS_SUCCESS_OK.getCode())
                    .data(iCandidatePassService.getCandidatePassStepNames(examId,candidateId))
                    .build();
        } catch (Exception e) {
            log.error("获取跳过考试步骤异常", e);
            return ApiResponse.<List<String>>builder().code(BizStatusCode.PASS_STEP_FAIL.getCode()).build();
        }
    }


    @ApiOperation(value = "6.9 记录人脸核身验证失败接口")
    @ApiOperationSort(9)
    @PostMapping("/faceVerifyFail")
    public ApiResponse<FaceAuthFailVO> faceVerifyFail(@Validated @RequestBody FaceAuthFailParam faceAuthFailParam) {
        try {
            log.info("人脸核身验证失败：{}", faceAuthFailParam);
            ApiResponse.ApiResponseBuilder<FaceAuthFailVO> builder = ApiResponse.builder();

            return builder
                    .code(BizStatusCode.KS_SUCCESS_OK.getCode())
                    .data(iCandidateProcessService.faceVerifyFail(faceAuthFailParam))
                    .build();
        } catch (KsException e) {
            log.error("记录人脸核身验证失败接口报业务错误：", e);
            return ApiResponse.<FaceAuthFailVO>builder().code(e.getErrCode()).build();
        } catch (Exception e) {
            log.error("记录人脸核身验证失败接口报内部错误：", e);
            return ApiResponse.<FaceAuthFailVO>builder().code(BizStatusCode.CANDIDATE_FACE_VERIFY_FAIL.getCode()).build();
        }
    }

    @ApiOperation(value = "6.10 考生举手取消")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "examId", value = "考试项目id", dataType = DataType.STRING,
                    paramType = ParamType.QUERY, required = true),
            @ApiImplicitParam(name = "candidateId", value = "考生ID", dataType = DataType.STRING,
                    paramType = ParamType.QUERY, required = true)
    })
    @ApiOperationSort(10)
    @GetMapping("handUpCancel")
    public ApiResponse handUpCancel(@RequestParam String examId, @RequestParam String candidateId) {
        return kwClient.handUpCancel(examId, candidateId);
    }
}
